package com.swj.auth.service.impl;

import com.swj.auth.service.ISysPasswordService;
import com.swj.auth.service.ISysRecordLogService;
import com.swj.common.core.constant.CacheConstants;
import com.swj.common.core.constant.Constants;
import com.swj.common.core.exception.user.UserLoginFailException;
import com.swj.common.core.model.SysUser;
import com.swj.common.redis.service.IRedisService;
import com.swj.common.security.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class SysPasswordServiceImpl implements ISysPasswordService {
    @Autowired
    private IRedisService redisService;

    @Autowired
    private ISysRecordLogService recordLogService;

    /**
     * redis密码错误次数缓存的键名
     *
     * @param userName 用户名
     * @return 缓存键key
     */
    private String getCacheKey(String userName) {
        return CacheConstants.PWD_ERR_CNT_KEY + userName;
    }

    @Override
    public void validate(SysUser user, String password) {

        String userName = user.getUserName();

        Integer retryCount = redisService.getObject(getCacheKey(userName));

        if (retryCount == null) {
            retryCount = 0;
        }

        if (retryCount >= CacheConstants.PASSWORD_MAX_RETRY_COUNT) {
            String errMsg = String.format("密码输入错误%s次，帐户锁定%s分钟", retryCount, CacheConstants.PASSWORD_LOCK_TIME);
            log.info(errMsg);
            recordLogService.recordLogininfor(userName, Constants.LOGIN_FAIL, errMsg);
            throw new UserLoginFailException(errMsg);
        }

        if (!matches(user, password)) {
            retryCount++;
            recordLogService.recordLogininfor(userName, Constants.LOGIN_FAIL, String.format("密码输入错误%s次", retryCount));
            log.info("密码输入错误{}次", retryCount);
            log.info("登录失败,用户不存在/密码错误");
            redisService.setExpireObject(getCacheKey(userName), retryCount, CacheConstants.PASSWORD_LOCK_TIME, TimeUnit.MINUTES);
            throw new RuntimeException("用户不存在/密码错误");
        } else {
            this.clearLoginRecordCache(userName);
        }
    }

    public boolean matches(SysUser user, String rawPassword) {
        return SecurityUtil.matchesPassword(rawPassword, user.getPassword());
    }

    public void clearLoginRecordCache(String loginName) {
        if (redisService.hasKey(getCacheKey(loginName))) {
            redisService.deleteObject(this.getCacheKey(loginName));
        }
    }
}
